package com.framework.buss.bridge.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.framework.buss.bridge.em.DataTypeEnum;
import com.framework.buss.bridge.model.BridgeTemplate;
import com.framework.buss.bridge.model.BridgeValue;
import com.framework.buss.bridge.mapper.BridgeTemplateMapper;
import com.framework.buss.bridge.mapper.BridgeValueMapper;
import com.framework.buss.bridge.service.IBridgeTemplateFileService;
import com.framework.buss.bridge.service.IBridgeValueService;
import com.framework.buss.bridge.vo.BridgeTemplateVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 桥梁报表值
 * @Author: jeecg-boot
 * @Date:   2023-04-02
 * @Version: V1.0
 */
@Service
public class BridgeValueServiceImpl extends ServiceImpl<BridgeValueMapper, BridgeValue> implements IBridgeValueService {
    @Value("${jeecg.path.data:/}")
    private String path;
    @Autowired
    private BridgeTemplateMapper templateMapper;
    @Autowired
    private IBridgeTemplateFileService bridgeTemplateFileService;

    public void exportWord(HttpServletResponse response, String bridgeId) {
        BridgeTemplate bridgeTemplate = new BridgeTemplate();
        bridgeTemplate.setBridgeId(bridgeId);
        List<BridgeTemplateVO> templateVOList = templateMapper.findAll(bridgeTemplate);
        Map<String, Object> params = new HashMap<>();

        // 单表数据,字符串 来源为表格
        Map<String, List<BridgeTemplateVO>> map = templateVOList.stream().filter(it->{
            if (DataTypeEnum.STRING.code.equals(it.getType()) &&
                    StringUtils.isNotBlank(it.getSourceTable()) &&
                    it.isLeaf() &&
                    "table".equals(it.getDataFrom()) &&
                    StringUtils.isBlank(it.getPid())) {
                return true;
            }
            return false;
        }).collect(Collectors.groupingBy(BridgeTemplateVO::getSourceTable));

        List<BridgeTemplateVO> sqlList = templateVOList.stream().filter(it->{
            if (DataTypeEnum.STRING.code.equals(it.getType()) &&
                    StringUtils.isNotBlank(it.getSourceTable()) &&
                    it.isLeaf() &&
                    "sql".equals(it.getDataFrom()) &&
                    StringUtils.isBlank(it.getPid())) {
                return true;
            }
            return false;
        }).collect(Collectors.toList());

        // 静态数据
        List<BridgeTemplateVO> staticList = templateVOList.stream().filter(it->{
            if (DataTypeEnum.STATIC.code.equals(it.getType())) {
                return true;
            }
            return false;
        }).collect(Collectors.toList());

        // 列表数据
        List<BridgeTemplateVO> arrList = templateVOList.stream().filter(it->{
            if (DataTypeEnum.LIST.code.equals(it.getType()) || DataTypeEnum.TABLE.code.equals(it.getType())) {
                return true;
            }
            return false;
        }).collect(Collectors.toList());

        setArrayData(params, arrList, bridgeId);

        setStringDataFromSql(params, sqlList, bridgeId);

        setStringData(params, map, bridgeId);

        // 表格循环数据
        List<BridgeTemplateVO> tableList = templateVOList.stream().filter(it->{
            if (DataTypeEnum.TABLE.code.equals(it.getType())) {
                return true;
            }
            return false;
        }).collect(Collectors.toList());

        staticList.forEach(it -> {
            params.put(it.getTitle(), it.getDefaultValue());
        });

        XWPFTemplate template = null;
        OutputStream os = null;
        try {
            // 生成配置文件
            Configure configure = addPolicy(tableList);

            // 读取文档
            String filePath = bridgeTemplateFileService.findFileId(bridgeId);
            // File file = ResourceUtils.getFile("classpath:template/report-month.docx");
            File file = new File(filePath);
            // 生成文档
            template = XWPFTemplate.compile(file, configure)
                    .render(params);
            String name = "健康监测月度报告";
            String fileName = new String(name.getBytes("UTF-8"), "ISO-8859-1");
            response.reset(); // 非常重要
            response.setContentType("application/octet-stream;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
            response.addHeader("Pargam", "no-cache");
            response.addHeader("Cache-Control", "no-cache");
            os = response.getOutputStream();
            template.write(os);
            os.flush();
        } catch (FileNotFoundException e) {
            log.error(e.getMessage(), e);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        } finally {
            if (null != template) {
                try {
                    template.close();
                } catch (IOException e) {
                   log.error(e.getMessage(), e);
                }
            }
            if (null != os) {
                try {
                    os.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
    }

    private void setStringDataFromSql(Map<String, Object> params, List<BridgeTemplateVO> sqlList, String bridgeId) {
        Map<String, String> sqlParams = new HashMap<>();
        // 默认参数
        sqlParams.put("bridgeId", bridgeId);
        sqlList.forEach(it -> {
            String sql = it.getSourceSql();
            if (StringUtils.isBlank(sql)) {
                return;
            }
            sqlParams.put("sql", sql);
            List<Map<String, Object>> list = baseMapper.executeSql(sqlParams);
            if (list.size() > 0) {
                Map<String, Object> map = list.get(0);
                Set entrySet = map.entrySet();
                Iterator iterator = entrySet.iterator();
                // 取值第一列
                Object key = iterator.next();
                // 从数据库查询值放入列表
                params.put(it.getTitle(), map.get(key));
            }
        });
    }

    private void setStringData(Map<String, Object> params, Map<String, List<BridgeTemplateVO>> map, String bridgeId) {
        // 从表中查询值， 表的字段类型要和 BridgeValue 一样
        map.forEach((k, v) -> {
            List<BridgeValue> list = baseMapper.findByBridgeId(k, bridgeId);
            Map<String, BridgeValue> itMap = list.stream().collect(Collectors.toMap(BridgeValue::getTitle, it->it, (v1, v2 )-> v2));
            List<String> itTitle = v.stream().map(BridgeTemplateVO::getTitle).collect(Collectors.toList());
            itTitle.forEach(it -> {
                BridgeValue bridgeValue = itMap.get(it);
                String value = bridgeValue.getValue();
                if (StringUtils.isBlank(value)) {
                    value = StringUtils.EMPTY;
                }
                params.put(it, value);
            });
        });
    }

    /**
     * 设置列表或者表格的数据
     * @param params 数据
     * @param arrList 模板配置
     */
    private void setArrayData(Map<String, Object> params, List<BridgeTemplateVO> arrList, String bridgeId) {
        Map<String, String> sqlParams = new HashMap<>();
        // 默认参数
        sqlParams.put("bridgeId", bridgeId);
        arrList.forEach(it -> {
            String sql = it.getSourceSql();
            if (StringUtils.isBlank(sql)) {
                return;
            }
            sqlParams.put("sql", sql);
            List<Map<String, Object>> list = baseMapper.executeSql(sqlParams);
            if (list.size() == 0) {
                return;
            }
            BridgeTemplate bridgeTemplate = new BridgeTemplate();
            bridgeTemplate.setBridgeId(bridgeId);
            bridgeTemplate.setPid(it.getId());
            List<BridgeTemplateVO> templateVOList = templateMapper.findAll(bridgeTemplate);
            Map<String, BridgeTemplateVO> columnType = templateVOList.stream().filter(child -> DataTypeEnum.IMAGE.code.equals(child.getType()))
                    .collect(Collectors.toMap(BridgeTemplateVO::getTitle, item->item, (key1, key2) -> key2));
            if (columnType.isEmpty()) {
                // 从数据库查询值放入列表
                params.put(it.getTitle(), list);
                return;
            }

            list.forEach(columns -> {
                columns.forEach((k, v) -> {
                    if (null == columnType.get(k)) {
                        return;
                    }
                    PictureRenderData renderData = new PictureRenderData() {
                        @Override
                        public byte[] readPictureData() {
                            String value = String.valueOf(v);
                            return value.getBytes();
                        }
                    };

                    renderData.setAltMeta("图片不存在");
                    columns.put(k, renderData);
                });
            });
            params.put(it.getTitle(), list);
        });
    }

    // 增加插件
    private Configure addPolicy(List<BridgeTemplateVO> templateList) {
        LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
        ConfigureBuilder builder = Configure.builder();
        // 表格
        templateList.forEach(it -> {
            builder.bind(it.getTitle(), policy);
        });
        Configure config = builder.build();
        return config;
    }

    @Override
    public void insertAll(List<BridgeTemplateVO> saveList) {
        if (saveList.size() == 0) {
            return;
        }
        // 删除旧数据
        BridgeTemplateVO first = saveList.get(0);
        baseMapper.deleteByBridgeId(first.getBridgeId());

        List<BridgeValue> list = new ArrayList<>();
        saveList.forEach(it -> {
            BridgeValue item = new BridgeValue();
            item.setVersion(it.getVersion());
            item.setValue(it.getDefaultValue());
            item.setTitle(it.getTitle());
            item.setBridgeId(it.getBridgeId());
            list.add(item);
        });
        this.saveBatch(list);
    }
}
